package com.lagou.filter;

import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.rpc.*;
import org.springframework.util.CollectionUtils;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;


@Activate(group = {CommonConstants.CONSUMER})
public class DubboInvokeFilter implements Runnable, Filter {

    Map<String, List<Long>> methodTimes = new ConcurrentHashMap<>();

    public DubboInvokeFilter() {
        Executors.newSingleThreadScheduledExecutor()
                .scheduleWithFixedDelay(this, 5, 5, TimeUnit.SECONDS);
    }

    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        long startTime = System.currentTimeMillis();
        long takeTime;
        Result result;
        try {
            result = invoker.invoke(invocation);
            if (result.getException() instanceof Exception) {
                throw new Exception(result.getException());
            }
            takeTime = System.currentTimeMillis() - startTime;
        } catch (Exception e) {
            e.printStackTrace();
            return invoker.invoke(invocation);
        }
        String methodName = invocation.getMethodName();
        List<Long> takeTimes = methodTimes.get(methodName);
        if (takeTimes == null) {
            takeTimes = new ArrayList<>();
        }
        takeTimes.add(takeTime);
        methodTimes.put(invocation.getMethodName(), takeTimes);
        return result;
    }

    private long getTP(List<Long> takeTimes, double rate) {
        if (CollectionUtils.isEmpty(takeTimes)) {
            System.out.println("takeTimes为空，返回……………………………………………………………………………………");
            return 0;
        }
        takeTimes = takeTimes.stream().sorted((o1, o2) -> (int) (o1 - o2))
                .collect(Collectors.toList());
        int index = (int) (takeTimes.size() * rate);
        return takeTimes.get(index);
    }

    @Override
    public void run() {
        Date date = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        System.out.println("开始打印TP时间……………………………………………………………………………………");
        for (Map.Entry<String, List<Long>> methods : methodTimes.entrySet()) {
            System.out.println("方法"+methods.getKey()+"的TP为："+ "TP90——>" + getTP(methods.getValue(), 0.9) + "毫秒    "
                    + "TP99——>" + getTP(methods.getValue(), 0.99) + "毫秒");
        }
    }
}
